from flask import request, jsonify, g
from flask_jwt_extended import jwt_required
import datetime
from bson import ObjectId

from app.api.v1 import api_bp
from app import mongo
from app.utils.auth import permission_required
from app.schemas.payment import PaymentSchema, PaymentCreateSchema, PaymentProcessSchema
from app.utils.common import normalize_data, paginate, generate_id

@api_bp.route('/payments', methods=['GET'])
@jwt_required()
@permission_required('payment:read')
def get_payments():
    """获取支付列表"""
    # 获取查询参数
    page = request.args.get('page', 1, type=int)
    limit = request.args.get('limit', 20, type=int)
    sort_by = request.args.get('sortBy', 'createdAt')
    order = request.args.get('order', 'desc')
    
    # 构建查询条件
    query = {}
    
    # 按患者ID筛选
    patient_id = request.args.get('patientId')
    if patient_id:
        query['patientId'] = patient_id
    
    # 按账单ID筛选
    billing_id = request.args.get('billingId')
    if billing_id:
        query['billingId'] = billing_id
    
    # 按关联类型筛选
    related_type = request.args.get('relatedType')
    if related_type:
        query['relatedType'] = related_type
    
    # 按关联ID筛选
    related_id = request.args.get('relatedId')
    if related_id:
        query['relatedId'] = related_id
    
    # 按状态筛选
    status = request.args.get('status')
    if status and status != 'all':
        query['status'] = status
    
    # 按支付方式筛选
    payment_method = request.args.get('paymentMethod')
    if payment_method and payment_method != 'all':
        query['paymentMethod'] = payment_method
    
    # 按日期范围筛选
    start_date = request.args.get('startDate')
    if start_date:
        try:
            start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
            query['createdAt'] = {'$gte': start_date}
        except ValueError:
            pass
    
    end_date = request.args.get('endDate')
    if end_date:
        try:
            end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
            end_date = end_date.replace(hour=23, minute=59, second=59)
            if 'createdAt' in query:
                query['createdAt']['$lte'] = end_date
            else:
                query['createdAt'] = {'$lte': end_date}
        except ValueError:
            pass
    
    # 确定排序
    sort_direction = -1 if order.lower() == 'desc' else 1
    
    # 获取数据
    payments_cursor = mongo.db.payments.find(query).sort(sort_by, sort_direction)
    
    # 分页
    paginated_data = paginate(payments_cursor, page, limit)
    
    # 标准化数据
    payments = []
    for payment in paginated_data['items']:
        # 获取患者信息
        patient_name = ''
        if 'patientId' in payment:
            patient_id = payment['patientId']
            if isinstance(patient_id, str) and ObjectId.is_valid(patient_id):
                patient_id = ObjectId(patient_id)
            patient = mongo.db.patients.find_one({'_id': patient_id})
            if patient:
                patient_name = patient.get('name', '')
        
        # 标准化支付数据
        normalized_payment = normalize_data(payment)
        normalized_payment['patientName'] = patient_name
        payments.append(normalized_payment)
    
    return jsonify({
        'success': True,
        'data': {
            'total': paginated_data['total'],
            'page': paginated_data['page'],
            'limit': paginated_data['per_page'],
            'payments': payments
        }
    }), 200

@api_bp.route('/payments/<id>', methods=['GET'])
@jwt_required()
@permission_required('payment:read')
def get_payment(id):
    """获取支付详情"""
    # 查询支付
    payment = None
    if ObjectId.is_valid(id):
        payment = mongo.db.payments.find_one({'_id': ObjectId(id)})
    
    if not payment:
        payment = mongo.db.payments.find_one({'paymentId': id})
    
    if not payment:
        return jsonify({
            'success': False,
            'message': '支付记录不存在'
        }), 404
    
    # 获取患者信息
    patient_info = None
    if 'patientId' in payment:
        patient_id = payment['patientId']
        if isinstance(patient_id, str) and ObjectId.is_valid(patient_id):
            patient_id = ObjectId(patient_id)
        patient = mongo.db.patients.find_one({'_id': patient_id})
        if patient:
            patient_info = {
                'id': str(patient['_id']),
                'patientId': patient.get('patientId', ''),
                'name': patient.get('name', ''),
                'gender': patient.get('gender', ''),
                'age': patient.get('age', '')
            }
    
    # 获取账单信息
    billing_info = None
    if 'billingId' in payment:
        billing_id = payment['billingId']
        if ObjectId.is_valid(billing_id):
            billing = mongo.db.billings.find_one({'_id': ObjectId(billing_id)})
        else:
            billing = mongo.db.billings.find_one({'billingId': billing_id})
        
        if billing:
            billing_info = {
                'id': str(billing['_id']),
                'billingId': billing.get('billingId', ''),
                'totalAmount': billing.get('totalAmount', 0),
                'status': billing.get('status', '')
            }
    
    # 标准化数据
    normalized_payment = normalize_data(payment)
    
    return jsonify({
        'success': True,
        'data': {
            'payment': normalized_payment,
            'patientInfo': patient_info,
            'billingInfo': billing_info
        }
    }), 200

@api_bp.route('/payments', methods=['POST'])
@jwt_required()
@permission_required('payment:create')
def create_payment():
    """创建支付记录"""
    # 验证请求数据
    schema = PaymentCreateSchema()
    errors = schema.validate(request.json)
    if errors:
        return jsonify({
            'success': False,
            'message': '请求数据验证失败',
            'errors': errors
        }), 400
    
    data = request.json
    
    # 验证患者是否存在
    patient_id = data.get('patientId')
    if not mongo.db.patients.find_one({'_id': ObjectId(patient_id)}):
        return jsonify({
            'success': False,
            'message': '患者不存在'
        }), 400
    
    # 如果提供了账单ID，验证账单是否存在
    if 'billingId' in data and data['billingId']:
        billing_id = data['billingId']
        billing = None
        
        if ObjectId.is_valid(billing_id):
            billing = mongo.db.billings.find_one({'_id': ObjectId(billing_id)})
        
        if not billing:
            billing = mongo.db.billings.find_one({'billingId': billing_id})
        
        if not billing:
            return jsonify({
                'success': False,
                'message': '关联的账单不存在'
            }), 400
        
        # 检查账单状态
        if billing.get('status') == '已支付':
            return jsonify({
                'success': False,
                'message': '账单已支付，无法重复支付'
            }), 400
        
        # 如果没有提供支付项目，使用账单项目
        if ('items' not in data or not data['items']) and 'items' in billing:
            data['items'] = []
            for item in billing['items']:
                data['items'].append({
                    'type': item.get('type', 'other'),
                    'itemId': str(billing['_id']),
                    'amount': item.get('amount', 0)
                })
        
        # 如果账单ID为ObjectId，转换为字符串
        if ObjectId.is_valid(billing_id) and isinstance(billing_id, ObjectId):
            data['billingId'] = str(billing_id)
        else:
            data['billingId'] = billing_id
    
    # 生成支付ID
    data['paymentId'] = generate_id('P')
    
    # 设置初始状态
    data['status'] = '待支付'
    
    # 设置totalAmount与amount保持一致
    if 'amount' in data and 'totalAmount' not in data:
        data['totalAmount'] = data['amount']
    
    # 设置创建时间和更新时间
    now = datetime.datetime.utcnow()
    data['createdAt'] = now
    data['updatedAt'] = now
    
    # 保存到数据库
    result = mongo.db.payments.insert_one(data)
    
    return jsonify({
        'success': True,
        'message': '支付记录创建成功',
        'data': {
            'id': str(result.inserted_id),
            'paymentId': data['paymentId'],
            'amount': data['amount'],
            'status': data['status'],
            'createdAt': now.isoformat()
        }
    }), 201

@api_bp.route('/payments/<id>/process', methods=['PUT'])
@jwt_required()
@permission_required('payment:update')
def process_payment(id):
    """处理支付结果"""
    # 查询支付记录
    payment = None
    if ObjectId.is_valid(id):
        payment = mongo.db.payments.find_one({'_id': ObjectId(id)})
    
    if not payment:
        payment = mongo.db.payments.find_one({'paymentId': id})
    
    if not payment:
        return jsonify({
            'success': False,
            'message': '支付记录不存在'
        }), 404
    
    # 验证支付状态
    if payment.get('status') not in ['待支付', '处理中']:
        return jsonify({
            'success': False,
            'message': f'当前支付状态为{payment.get("status")}，无法处理'
        }), 400
    
    # 验证请求数据
    schema = PaymentProcessSchema()
    errors = schema.validate(request.json)
    if errors:
        return jsonify({
            'success': False,
            'message': '请求数据验证失败',
            'errors': errors
        }), 400
    
    data = request.json
    
    # 更新支付记录
    update_data = {
        'status': data.get('status'),
        'updatedAt': datetime.datetime.utcnow()
    }
    
    # 如果支付成功，记录支付时间
    if data.get('status') == '成功':
        update_data['paidAt'] = datetime.datetime.utcnow()
        
        # 确保totalAmount字段与amount保持一致
        if 'totalAmount' not in payment and 'amount' in payment:
            update_data['totalAmount'] = payment['amount']
    
    # 更新支付方式（如果提供）
    if 'paymentMethod' in data:
        update_data['paymentMethod'] = data['paymentMethod']
    
    # 更新交易ID（如果提供）
    if 'transactionId' in data:
        update_data['transactionId'] = data['transactionId']
    
    # 更新数据库
    mongo.db.payments.update_one({'_id': ObjectId(payment['_id'])}, {'$set': update_data})
    
    # 如果支付成功且关联了账单，更新账单状态
    if data.get('status') == '成功' and 'billingId' in payment:
        billing_id = payment['billingId']
        
        # 查找账单
        billing = None
        if ObjectId.is_valid(billing_id):
            billing = mongo.db.billings.find_one({'_id': ObjectId(billing_id)})
        else:
            billing = mongo.db.billings.find_one({'billingId': billing_id})
        
        if billing:
            # 更新账单状态为已支付
            mongo.db.billings.update_one(
                {'_id': billing['_id']},
                {'$set': {'status': '已支付', 'updatedAt': datetime.datetime.utcnow()}}
            )
    
    return jsonify({
        'success': True,
        'message': f'支付状态已更新为{data.get("status")}',
        'data': {
            'id': str(payment['_id']),
            'paymentId': payment.get('paymentId'),
            'status': data.get('status')
        }
    }), 200

@api_bp.route('/payments/<id>/cancel', methods=['PUT'])
@jwt_required()
@permission_required('payment:update')
def cancel_payment(id):
    """取消支付"""
    # 查询支付记录
    payment = None
    if ObjectId.is_valid(id):
        payment = mongo.db.payments.find_one({'_id': ObjectId(id)})
    
    if not payment:
        payment = mongo.db.payments.find_one({'paymentId': id})
    
    if not payment:
        return jsonify({
            'success': False,
            'message': '支付记录不存在'
        }), 404
    
    # 验证支付状态
    if payment.get('status') not in ['待支付', '处理中']:
        return jsonify({
            'success': False,
            'message': f'当前支付状态为{payment.get("status")}，无法取消'
        }), 400
    
    # 更新支付记录
    update_data = {
        'status': '已取消',
        'updatedAt': datetime.datetime.utcnow()
    }
    
    # 更新数据库
    mongo.db.payments.update_one({'_id': ObjectId(payment['_id'])}, {'$set': update_data})
    
    return jsonify({
        'success': True,
        'message': '支付已取消',
        'data': {
            'id': str(payment['_id']),
            'paymentId': payment.get('paymentId'),
            'status': '已取消'
        }
    }), 200

@api_bp.route('/payments/<id>/refund', methods=['PUT'])
@jwt_required()
@permission_required('payment:update')
def refund_payment(id):
    """退款处理"""
    # 查询支付记录
    payment = None
    if ObjectId.is_valid(id):
        payment = mongo.db.payments.find_one({'_id': ObjectId(id)})
    
    if not payment:
        payment = mongo.db.payments.find_one({'paymentId': id})
    
    if not payment:
        return jsonify({
            'success': False,
            'message': '支付记录不存在'
        }), 404
    
    # 验证支付状态
    if payment.get('status') != '成功':
        return jsonify({
            'success': False,
            'message': f'当前支付状态为{payment.get("status")}，仅支持对成功的支付进行退款'
        }), 400
    
    # 更新支付记录
    update_data = {
        'status': '已退款',
        'updatedAt': datetime.datetime.utcnow()
    }
    
    # 获取原始金额（如果存在），并添加负值的totalAmount表示退款
    if 'amount' in payment:
        update_data['refundAmount'] = -payment['amount']
        # 如果没有totalAmount字段，添加它
        if 'totalAmount' not in payment:
            update_data['totalAmount'] = -payment['amount']
    
    # 更新数据库
    mongo.db.payments.update_one({'_id': ObjectId(payment['_id'])}, {'$set': update_data})
    
    # 如果关联了账单，更新账单状态
    if 'billingId' in payment:
        billing_id = payment['billingId']
        
        # 查找账单
        billing = None
        if ObjectId.is_valid(billing_id):
            billing = mongo.db.billings.find_one({'_id': ObjectId(billing_id)})
        else:
            billing = mongo.db.billings.find_one({'billingId': billing_id})
        
        if billing:
            # 更新账单状态为已退款
            mongo.db.billings.update_one(
                {'_id': billing['_id']},
                {'$set': {'status': '已退款', 'updatedAt': datetime.datetime.utcnow()}}
            )
    
    return jsonify({
        'success': True,
        'message': '退款处理成功',
        'data': {
            'id': str(payment['_id']),
            'paymentId': payment.get('paymentId'),
            'status': '已退款'
        }
    }), 200

@api_bp.route('/patients/<patient_id>/payments/summary', methods=['GET'])
@jwt_required()
@permission_required('payment:read')
def get_patient_payment_summary(patient_id):
    """获取患者支付记录摘要"""
    # 验证患者是否存在
    if not mongo.db.patients.find_one({'_id': ObjectId(patient_id)}):
        return jsonify({
            'success': False,
            'message': '患者不存在'
        }), 404
    
    # 按支付状态统计
    status_stats = list(mongo.db.payments.aggregate([
        {'$match': {'patientId': patient_id}},
        {'$group': {
            '_id': '$status',
            'count': {'$sum': 1},
            'amount': {'$sum': '$totalAmount'}
        }},
        {'$sort': {'_id': 1}}
    ]))
    
    # 按关联类型统计
    type_stats = list(mongo.db.payments.aggregate([
        {'$match': {'patientId': patient_id}},
        {'$group': {
            '_id': '$relatedType',
            'count': {'$sum': 1},
            'amount': {'$sum': '$totalAmount'}
        }},
        {'$sort': {'_id': 1}}
    ]))
    
    # 获取最近的支付记录
    recent_payments = list(mongo.db.payments.find(
        {'patientId': patient_id}
    ).sort('createdAt', -1).limit(5))
    
    # 总计
    total_stats = list(mongo.db.payments.aggregate([
        {'$match': {'patientId': patient_id}},
        {'$group': {
            '_id': None,
            'totalCount': {'$sum': 1},
            'totalAmount': {'$sum': '$totalAmount'},
            'paidAmount': {'$sum': {
                '$cond': [{'$eq': ['$status', '成功']}, '$totalAmount', 0]
            }},
            'pendingAmount': {'$sum': {
                '$cond': [{'$eq': ['$status', '待支付']}, '$totalAmount', 0]
            }}
        }}
    ]))
    
    # 标准化数据
    normalized_recent = [normalize_data(payment) for payment in recent_payments]
    
    # 构建响应
    summary = {
        'byStatus': status_stats,
        'byType': type_stats,
        'recent': normalized_recent,
        'total': total_stats[0] if total_stats else {
            'totalCount': 0,
            'totalAmount': 0,
            'paidAmount': 0,
            'pendingAmount': 0
        }
    }
    
    return jsonify({
        'success': True,
        'data': summary
    }), 200 